<template>
  <div class="responsive-scroll" ref="scrollContainerRef">
    <!-- 左侧滚动按钮 -->
    <div
      v-show="showArrow"
      class="scroll-arrow scroll-arrow-left"
      :class="{ disabled: !canScrollLeft }"
      @click="handleScrollLeft"
    >
      <el-icon><ArrowLeft /></el-icon>
    </div>

    <!-- 滚动内容区域 -->
    <div
      class="scroll-container"
      ref="scrollContentRef"
      @scroll="handleScroll"
      @wheel="handleWheelScroll"
    >
      <div class="scroll-content">
        <slot></slot>
      </div>
    </div>

    <!-- 右侧滚动按钮 -->
    <div
      v-show="showArrow"
      class="scroll-arrow scroll-arrow-right"
      :class="{ disabled: !canScrollRight }"
      @click="handleScrollRight"
    >
      <el-icon><ArrowRight /></el-icon>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, nextTick, computed } from 'vue'
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue'

// 定义组件属性
interface Props {
  scrollStep?: number // 每次滚动的步长
  behavior?: ScrollBehavior // 滚动行为：smooth 或 auto
}

const props = withDefaults(defineProps<Props>(), {
  scrollStep: 200,
  behavior: 'smooth'
})

// 引用和状态
const scrollContainerRef = ref<HTMLElement | null>(null)
const scrollContentRef = ref<HTMLElement | null>(null)
const currentScrollLeft = ref(0)
const isScrolling = ref(false)
const showArrow = ref(false)
const contentWidth = ref(0)
const containerWidth = ref(0)

// 计算属性
const canScrollLeft = computed(() => currentScrollLeft.value > 0)
const canScrollRight = computed(() => {
  return contentWidth.value > containerWidth.value &&
         currentScrollLeft.value < contentWidth.value - containerWidth.value;
})

/**
 * 处理滚动事件
 */
const handleScroll = () => {
  if (!scrollContentRef.value) return

  // 更新滚动位置
  currentScrollLeft.value = scrollContentRef.value.scrollLeft

  // 设置滚动状态
  if (!isScrolling.value) {
    isScrolling.value = true
    setTimeout(() => {
      isScrolling.value = false
    }, 150) // 滚动结束后的缓冲时间
  }
}

/**
 * 处理鼠标滚轮滚动
 */
const handleWheelScroll = (event: WheelEvent) => {
  if (!scrollContentRef.value) return

  // 根据滚轮方向调整滚动位置
  scrollContentRef.value.scrollLeft += event.deltaY > 0 ? props.scrollStep : -props.scrollStep
}

/**
 * 向左滚动
 */
const handleScrollLeft = () => {
  if (!scrollContentRef.value || isScrolling.value || !canScrollLeft.value) return

  const targetPosition = Math.max(0, scrollContentRef.value.scrollLeft - props.scrollStep)

  scrollContentRef.value.scrollTo({
    left: targetPosition,
    behavior: props.behavior
  })
}

/**
 * 向右滚动
 */
const handleScrollRight = () => {
  if (!scrollContentRef.value || isScrolling.value || !canScrollRight.value) return

  const maxScrollLeft = contentWidth.value - containerWidth.value

  const targetPosition = Math.min(
    maxScrollLeft,
    scrollContentRef.value.scrollLeft + props.scrollStep
  )

  scrollContentRef.value.scrollTo({
    left: targetPosition,
    behavior: props.behavior
  })
}

/**
 * 更新滚动状态
 */
const updateScrollState = () => {
  if (!scrollContentRef.value) return

  const { scrollLeft, scrollWidth, clientWidth } = scrollContentRef.value

  // 更新状态
  currentScrollLeft.value = scrollLeft
  contentWidth.value = scrollWidth
  containerWidth.value = clientWidth

  // 内容宽度大于容器宽度时显示箭头
  showArrow.value = scrollWidth > clientWidth
}

/**
 * 窗口大小变化处理
 */
const handleResize = () => {
  nextTick(() => {
    updateScrollState()
  })
}

// 监听内容变化
const observeContentChanges = () => {
  if (!scrollContentRef.value) return

  const observer = new MutationObserver(() => {
    nextTick(() => {
      updateScrollState()
    })
  })

  observer.observe(scrollContentRef.value, {
    childList: true,
    subtree: true,
    attributes: true
  })

  return observer
}

let resizeObserver: ResizeObserver | null = null
let mutationObserver: MutationObserver | null = null

// 组件挂载后初始化
onMounted(() => {
  nextTick(() => {
    updateScrollState()

    // 使用 ResizeObserver 监听元素大小变化
    if (scrollContentRef.value && window.ResizeObserver) {
      resizeObserver = new ResizeObserver(handleResize)
      resizeObserver.observe(scrollContentRef.value)
    }

    // 监听内容变化
    mutationObserver = observeContentChanges()
  })

  window.addEventListener('resize', handleResize)
})

// 组件卸载前清理
onBeforeUnmount(() => {
  window.removeEventListener('resize', handleResize)

  if (resizeObserver) {
    resizeObserver.disconnect()
  }

  if (mutationObserver) {
    mutationObserver.disconnect()
  }
})
</script>

<style lang="scss" scoped>
.responsive-scroll {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;

  .scroll-container {
    flex: 1;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -ms-overflow-style: none;
    scroll-behavior: smooth;
    text-align: right;
    &::-webkit-scrollbar {
      display: none;
    }
  }

  .scroll-content {
    display: inline-flex;
    white-space: nowrap;
  }

  .scroll-arrow {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    box-shadow: 0 0 6px rgba(0, 0, 0, 0.12);
    cursor: pointer;
    z-index: 10;
    color: var(--el-text-color-secondary);
    transition: color 0.3s, transform 0.2s;

    &.disabled {
      color: var(--el-text-color-disabled);
      cursor: not-allowed;
      pointer-events: none;
    }

    &:not(.disabled):hover {
      color: var(--el-color-primary);
      transform: scale(1.05);
    }

    &:not(.disabled):active {
      transform: scale(0.95);
    }

    &-left {
      margin-right: 8px;
    }

    &-right {
      margin-left: 8px;
    }
  }
}
</style>